pub use std::{
    ops::Deref,
    sync::{Arc, Mutex},
};

pub use amiquip::{
    AmqpProperties, Channel, Connection, ExchangeDeclareOptions, ExchangeType, FieldTable, Publish,
    QueueDeclareOptions,
};
pub use serde::{Deserialize, Serialize};

pub use crate::{thread_safe_ptr, utils::thread_pool::SimplePool};

#[derive(Debug, Clone)]
pub struct MqBase {
    pub exchange_type: ExchangeType,
    pub exchange: String,
    pub queue: String,
    pub key: String,
}

impl MqBase {
    pub fn declare_and_bind(&self, channel: &Channel) {
        let exchange = channel
            .exchange_declare(
                self.exchange_type.clone(),
                self.exchange.as_str(),
                ExchangeDeclareOptions {
                    auto_delete: false,
                    durable: true,
                    internal: false,
                    arguments: FieldTable::default(),
                },
            )
            .unwrap();
        let queue = channel
            .queue_declare(
                self.queue.as_str(),
                QueueDeclareOptions {
                    auto_delete: false,
                    durable: true,
                    exclusive: false,
                    arguments: FieldTable::default(),
                },
            )
            .unwrap();
        channel
            .queue_bind(
                queue.name(),
                exchange.name(),
                self.key.as_str(),
                FieldTable::default(),
            )
            .unwrap();
    }
}

#[test]
pub fn test_json_mapper() {
    let msg = "{\"uniqueCode\":\"062602138AD0000E00000000000092C7\",\"companyId\":111,\"id\":1110120240325000003,\"partnerCode\":\"E230128001X001\",\"saleOrderCode\":\"SKP012430000436\",\"outType\":2,\"itemCount\":1,\"amount\":2.30,\"remark\":\"\",\"originalRemark\":\"\",\"areaCode\":230128100,\"payTime\":\"2024-03-25 16:13:58\",\"invoiceCreateTime\":\"2024-03-25 16:14:10\",\"workAreaId\":6,\"activityType\":0,\"supervisionCode\":\"2103124032500023\",\"orderType\":\"线下销售\",\"invoiceType\":\"电子发票\",\"receiveName\":\"马忠艳\",\"receivePhone\":\"18646105366\",\"provinceName\":\"黑龙江省\",\"cityName\":\"哈尔滨市\",\"districtName\":\"通河县\",\"streetName\":\"通河镇\",\"address\":\"通河镇富强街\",\"taxRate\":13.00,\"sn\":\"\",\"deliverFee\":0.00,\"warehouseId\":11101,\"beInvoiced\":0,\"drugstoreId\":\"563512\",\"beInvoiceAlone\":0,\"netTraceNo\":\"\",\"toWarehouseId\":null,\"sourceType\":5,\"subType\":null,\"subDrugstoreBranchId\":null,\"subDrugstoreBranchFullName\":null,\"outOrderItemRequestList\":[{\"id\":5059667,\"goodsCode\":\"PGC002003O\",\"batchNo\":\"20230801\",\"qty\":1,\"amount\":2.30,\"rowIndex\":1,\"realPrice\":2.300000,\"originPrice\":2.300000,\"taxRate\":13.00,\"workAreaId\":6,\"beGift\":0,\"remark\":\"\",\"drugId\":\"972\"}]}";
    println!("{msg}");
}

#[derive(Serialize, Deserialize, Default)]
pub(crate) struct OutOrderItemRequestList {
    id: i64,
    goodsCode: String,
    batchNo: String,
    qty: i64,
    amount: f64,
    rowIndex: i64,
    realPrice: f64,
    originPrice: f64,
    taxRate: i64,
    workAreaId: i64,
    beGift: i64,
    remark: String,
    drugId: String,
}

#[derive(Serialize, Deserialize, Default)]
struct RootInterface {
    uniqueCode: String,
    companyId: i64,
    id: i64,
    partnerCode: String,
    saleOrderCode: String,
    outType: i64,
    itemCount: i64,
    amount: f64,
    remark: String,
    originalRemark: String,
    areaCode: i64,
    payTime: String,
    invoiceCreateTime: String,
    workAreaId: i64,
    activityType: i64,
    supervisionCode: String,
    orderType: String,
    invoiceType: String,
    receiveName: String,
    receivePhone: String,
    provinceName: String,
    cityName: String,
    districtName: String,
    streetName: String,
    address: String,
    taxRate: i64,
    sn: String,
    deliverFee: i64,
    warehouseId: i64,
    beInvoiced: i64,
    drugstoreId: String,
    beInvoiceAlone: i64,
    netTraceNo: String,
    toWarehouseId: String,
    sourceType: i64,
    subType: String,
    subDrugstoreBranchId: String,
    subDrugstoreBranchFullName: String,
    outOrderItemRequestList: Vec<OutOrderItemRequestList>,
}

// #[test]
pub fn test_mq() {
    let mut conn = Connection::insecure_open("amqp://admin:leyo@@123@192.168.27.57:5672").unwrap();
    let channel = Arc::new(Mutex::new(conn.open_channel(None).unwrap()));
    let mq_base = MqBase {
        exchange_type: ExchangeType::Direct,
        exchange: "solar.exchange".to_string(),
        queue: "solar.queue.stock".to_string(),
        key: "solar.queue.stock".to_string(),
    };
    thread_safe_ptr!(mq_base);

    mq_base.declare_and_bind(channel.lock().unwrap().deref());
    let msg = "{\"uniqueCode\":\"062602138AD0000E00000000000092C7\",\"companyId\":111,\"id\":1110120240325000003,\"partnerCode\":\"E230128001X001\",\"saleOrderCode\":\"SKP012430000436\",\"outType\":2,\"itemCount\":1,\"amount\":2.30,\"remark\":\"\",\"originalRemark\":\"\",\"areaCode\":230128100,\"payTime\":\"2024-03-25 16:13:58\",\"invoiceCreateTime\":\"2024-03-25 16:14:10\",\"workAreaId\":6,\"activityType\":0,\"supervisionCode\":\"2103124032500023\",\"orderType\":\"线下销售\",\"invoiceType\":\"电子发票\",\"receiveName\":\"马忠艳\",\"receivePhone\":\"18646105366\",\"provinceName\":\"黑龙江省\",\"cityName\":\"哈尔滨市\",\"districtName\":\"通河县\",\"streetName\":\"通河镇\",\"address\":\"通河镇富强街\",\"taxRate\":13.00,\"sn\":\"\",\"deliverFee\":0.00,\"warehouseId\":11101,\"beInvoiced\":0,\"drugstoreId\":\"563512\",\"beInvoiceAlone\":0,\"netTraceNo\":\"\",\"toWarehouseId\":null,\"sourceType\":5,\"subType\":null,\"subDrugstoreBranchId\":null,\"subDrugstoreBranchFullName\":null,\"outOrderItemRequestList\":[{\"id\":5059667,\"goodsCode\":\"PGC002003O\",\"batchNo\":\"20230801\",\"qty\":1,\"amount\":2.30,\"rowIndex\":1,\"realPrice\":2.300000,\"originPrice\":2.300000,\"taxRate\":13.00,\"workAreaId\":6,\"beGift\":0,\"remark\":\"\",\"drugId\":\"972\"}]}";

    let mut prop = AmqpProperties::default();
    prop = prop
        .with_message_id("sad".to_string())
        .with_content_type("application/json".to_string())
        .with_content_encoding("UTF-8".to_string());
    let publish = Publish::with_properties(msg.as_bytes(), mq_base.key.as_str(), prop.clone());

    let mut pool = SimplePool::new(20);

    let vec = (0..)
        .take(100 * 10000)
        .map::<Box<(dyn FnOnce() + Send)>, _>(|a| {
            let ch = channel.clone();
            let publish_copy = publish.clone();
            Box::new(move || {
                ch.lock()
                    .unwrap()
                    .basic_publish(mq_base.exchange.as_str(), publish_copy)
                    .unwrap();
            })
        })
        .collect::<Vec<_>>();
    // vec.into_iter().for_each(|a| {
    //     a();
    // });
    let ch1 = conn.open_channel(None).unwrap();
    for x in 0..100 * 10000 {
        let vec1 = serde_json::to_vec(&RootInterface::default()).unwrap();
        let publish = Publish::with_properties(vec1.as_slice(), mq_base.key.as_str(), prop.clone());

        ch1.basic_publish(mq_base.exchange.as_str(), publish.clone())
            .unwrap();
    }

    // pool.submit_all(vec);

    pool.flush();
}

// 批量处理消息发送
pub fn send_batch(ch: Channel, messages: Vec<Vec<u8>>) {
    let mut prop = AmqpProperties::default();
    prop = prop
        .with_message_id("sad".to_string())
        .with_content_type("application/json".to_string())
        .with_content_encoding("UTF-8".to_string());
    messages.into_iter().for_each(|mm| {
        let publish = Publish::with_properties(mm.as_slice(), "solar.queue.stock", prop.clone());
        ch.basic_publish("solar.exchange", publish).unwrap();
    });
}

pub fn send_batch_async(thread_size: usize, conn: &mut Connection, messages: Vec<Vec<u8>>) {
    let mut pool = SimplePool::new(thread_size);

    messages
        .chunks(messages.len() / thread_size)
        .for_each(|mms| {
            let mms_copy = mms.iter().map(|m| m.clone()).collect::<Vec<_>>();
            let ch = conn.open_channel(None).unwrap();
            pool.submit(move || {
                send_batch(ch, mms_copy);
            });
        });
    pool.flush();
}
